﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;

namespace UpdateManager {
    /// <summary>
    /// 程序集管理类
    /// </summary>
    public class AssemblyManager {
        /// <summary>
        /// 获取本地程序集配置
        /// </summary>
        /// <returns></returns>
        public LocalAssemblyInfo GetLocalAssembly() {
            //本地配置信息实体
            LocalAssemblyInfo info = new LocalAssemblyInfo();

            try {
                //读取本地程序集Xml文件
                string localXmlPath = "LocalAssembly.xml";

                if (File.Exists(localXmlPath)) {
                    XElement xmlLocal = XElement.Load(localXmlPath);

                    //获取远程程序集XML地址
                    info.XmlPath = xmlLocal.Element("Host").Attribute("XmlPath").Value;
                    info.AutoStart = Convert.ToBoolean(xmlLocal.Element("StartApp").Attribute("IsStart").Value);
                    info.AppName = xmlLocal.Element("StartApp").Attribute("AppName").Value;
                    //获取已装程序的键值对，Key：程序集名称
                    info.AssemblyItems = xmlLocal.Element("Applications").Elements("Item")
                        .ToDictionary(k => k.Attribute("Name").Value, v => {
                            LocalAssemblyItemInfo item = new LocalAssemblyItemInfo();

                            item.IsTip = v.Attribute("IsTipNew") == null ? true :
                                Convert.ToBoolean(v.Attribute("IsTipNew").Value);
                            item.Version = v.Attribute("Version").Value;

                            return item;
                        });
                } else {
                    //读不到本地文件，使用默认值
                    info.XmlPath = "http://218.249.168.202/update/Assembly.xml";
                    info.AppName = "Leisure.exe";
                    info.AutoStart = true;
                }
            } catch {
                //读不到本地文件，使用默认值
                info.XmlPath = "http://218.249.168.202/update/Assembly.xml";
                info.AppName = "Leisure.exe";
                info.AutoStart = true;
            }

            return info;
        }

        /// <summary>
        /// 获取程序集信息
        /// </summary>
        public AssemblyInfo GetAssembly(LocalAssemblyInfo localAssembly) {
            //获取本地配置
            //LocalAssemblyInfo localAssembly = this.GetLocalAssembly();

            //声明新的程序集对象
            AssemblyInfo assembly = new AssemblyInfo();

            //判断是否已经连接网络
            if (DownloadManager.GetInternetConnectedState()) {
                try {
                    //获取网上的更新Xml配置文件
                    XElement xmlContent = XElement.Load(localAssembly.XmlPath);

                    //赋值程序集
                    assembly.RootUrl = xmlContent.Element("RootUrl").Value;
                    //主程序
                    var mainSoftwares = xmlContent.Element("MainSoftware").Elements("Item").Select(
                        item => {
                            AssemblyItemInfo info = new AssemblyItemInfo();
                            //赋值插件对象
                            info.AssemblyName = item.Attribute("Name").Value;
                            info.AssemblyText = item.Element("Text").Value;
                            info.Version = item.Element("Version").Value;
                            info.Author = item.Element("Author").Value;
                            info.Information = item.Element("Information").Value.Trim().Replace(" ", "");
                            info.PublishDate = Convert.ToDateTime(item.Element("PublishDate").Value);
                            info.IsNew = Convert.ToBoolean(item.Element("IsNew").Value);
                            info.Size = item.Element("Size").Value;
                            info.UpdateUrl = assembly.RootUrl + item.Element("UpdateUrl").Value;
                            info.IconUrl = assembly.RootUrl + item.Element("Icon").Value;
                            info.Type = AssemblyType.MainSoftware;
                            LocalAssemblyItemInfo localInfo = new LocalAssemblyItemInfo();
                            if (localAssembly.AssemblyItems.TryGetValue(info.AssemblyName, out localInfo)) {
                                info.OldVersion = localInfo.Version;
                                info.IsTip = localInfo.IsTip;
                            }

                            return info;
                        }).ToList();
                    //插件
                    var plugins = xmlContent.Element("Plugins").Elements("Item").Select(
                        item => {
                            AssemblyItemInfo info = new AssemblyItemInfo();
                            //赋值插件对象
                            info.AssemblyName = item.Attribute("Name").Value;
                            info.AssemblyText = item.Element("Text").Value;
                            info.Version = item.Element("Version").Value;
                            info.Author = item.Element("Author").Value;
                            info.Information = item.Element("Information").Value;
                            info.PublishDate = Convert.ToDateTime(item.Element("PublishDate").Value);
                            info.IsNew = Convert.ToBoolean(item.Element("IsNew").Value);
                            info.Size = item.Element("Size").Value;
                            info.UpdateUrl = assembly.RootUrl + item.Element("UpdateUrl").Value;
                            info.IconUrl = assembly.RootUrl + item.Element("Icon").Value;
                            info.Type = AssemblyType.Plugin;
                            LocalAssemblyItemInfo localInfo = new LocalAssemblyItemInfo();
                            if (localAssembly.AssemblyItems.TryGetValue(info.AssemblyName, out localInfo)) {
                                info.OldVersion = localInfo.Version;
                                info.IsTip = localInfo.IsTip;
                            }

                            return info;
                        }).ToList();

                    assembly.AutoStart = localAssembly.AutoStart;
                    assembly.AppName = localAssembly.AppName;
                    assembly.AssemblyItems = mainSoftwares.Concat(plugins).ToList();

                    //更新本地的配置
                    localAssembly.XmlPath = assembly.RootUrl + "Update/Assembly.xml";
                    this.ModifyLocalAssembly(localAssembly);
                } catch {
                }
            } else {
                
            }
            return assembly;
        }

        /// <summary>
        /// 修改本地配置
        /// </summary>
        /// <param name="info"></param>
        public void ModifyLocalAssembly(LocalAssemblyInfo info) {
            string xmlPath = "LocalAssembly.xml";

            //初始化指定的数据文件
            XDocument xmlDoc = new XDocument(
                new XElement("Assembly",
                    new XElement("Host", new XAttribute("XmlPath", info.XmlPath)),
                    new XElement("StartApp", new XAttribute("IsStart", info.AutoStart), new XAttribute("AppName", info.AppName)),
                    new XElement("Applications")));

            XElement el = xmlDoc.Element("Assembly").Element("Applications");

            foreach (string key in info.AssemblyItems.Keys) {
                XElement item = new XElement("Item",
                    new XAttribute("Name", key),
                    new XAttribute("Version", info.AssemblyItems[key].Version),
                    new XAttribute("IsTipNew", info.AssemblyItems[key].IsTip));

                el.Add(item);
            }

            //存储数据文件
            xmlDoc.Save(xmlPath);
        }

        /// <summary>
        /// 检查是否有更新
        /// </summary>
        /// <param name="assembly"></param>
        /// <returns></returns>
        public bool CheckUpdate() {
            LocalAssemblyInfo locaAssembly = this.GetLocalAssembly();

            //获取程序集信息
            AssemblyInfo assembly = this.GetAssembly(locaAssembly);
            //获取版本不同的程序集数量
            var differentCount = assembly.AssemblyItems
                .Select(s => s.OldVersion != s.Version && s.IsTip).Count();
            //返回是否有版本不同的程序集
            return differentCount > 0;
        }
    }
}
